package com.uduemc.biso.node.web.component;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.uduemc.biso.core.extities.center.Agent;
import com.uduemc.biso.core.extities.pojo.NginxServerConf;
import com.uduemc.biso.core.utils.TemplateUtil;
import com.uduemc.biso.node.core.property.GlobalProperties;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class NginxServerAgent {

	@Autowired
	private GlobalProperties globalProperties;

	@Autowired
	private VelocityEngine velocityEngine;

	@Autowired
	private NginxOperate nginxOperate;

	public String makeIncludePath(long agentId) {
		String basePath = globalProperties.getNginx().getVhosts();
		basePath = basePath + File.separator + "agent";
		String path = TemplateUtil.makeLocalDirectory(basePath, agentId);
		if (!FileUtil.isDirectory(path)) {
			FileUtil.mkdir(path);
		}
		return path;
	}

	public String makeIncludeFileName(String serverName) {
		String[] split = serverName.split("\\.");
		if (StrUtil.startWith(serverName, "*") && split[0].equals("*")) {
			serverName = StrUtil.replace(serverName, "*.", "_.");
		}
		return serverName + ".conf";
	}

	public String makeIncludeFile(long agentId, String serverName) {
		String makeIncludePath = makeIncludePath(agentId);
		return makeIncludePath + File.separator + makeIncludeFileName(serverName);
	}

	public String makeAccessLog(long agentId) throws IOException {
		return makeAccessLog(agentId, "access.log");
	}

	public String makeAccessLog(long agentId, String filename) throws IOException {
		String basePath = globalProperties.getNginx().getNginxLogs() + File.separator + "agent";
		basePath = TemplateUtil.makeLocalDirectory(basePath, agentId);
		if (!FileUtil.isDirectory(basePath)) {
			FileUtil.mkdir(basePath);
		}
		String path = basePath + File.separator + filename;
		File file = new File(path);
		if (!file.isFile()) {
			FileUtils.writeStringToFile(file, "start nginx access log\n", "UTF-8");
		}
		return path;
	}

	public String makeErrorLog(long agentId) throws IOException {
		return makeErrorLog(agentId, "error.log");
	}

	public String makeErrorLog(long agentId, String filename) throws IOException {
		String basePath = globalProperties.getNginx().getNginxLogs() + File.separator + "agent";
		basePath = TemplateUtil.makeLocalDirectory(basePath, agentId);
		if (!FileUtil.isDirectory(basePath)) {
			FileUtil.mkdir(basePath);
		}
		String path = basePath + File.separator + filename;
		File file = new File(path);
		if (!file.isFile()) {
			FileUtils.writeStringToFile(file, "start nginx error log\n", "UTF-8");
		}
		return path;
	}

	public String makeText(NginxServerConf ser) {
		String serverName = ser.getServerName();

		Map<String, Object> mapData = new HashMap<String, Object>();
		mapData.put("server", ser);
		VelocityContext ctx = new VelocityContext(mapData);

		Template t = null;

		String[] split = serverName.split("\\.");
		if (StrUtil.startWith(serverName, "*") && split[0].equals("*")) {
			t = velocityEngine.getTemplate("templates/velocity/nginx/server_universal_agent.vm");
		} else {
			t = velocityEngine.getTemplate("templates/velocity/nginx/server_agent.vm");
		}

		StringWriter sw = new StringWriter();
		t.merge(ctx, sw);
		String server = sw.toString();
		log.info(server);
		return server;
	}

	public boolean make(long agentId, NginxServerConf ser) throws IOException {
		String accessLog = ser.getAccessLog();
		String errorLog = ser.getErrorLog();
		if (StrUtil.isBlank(accessLog)) {
			ser.setAccessLog(makeAccessLog(agentId));
		}
		if (StrUtil.isBlank(errorLog)) {
			ser.setErrorLog(makeErrorLog(agentId));
		}
		String makeText = makeText(ser);
		String makeIncludeFile = makeIncludeFile(agentId, ser.getServerName());
		File file = new File(makeIncludeFile);
		if (file.isFile()) {
			file.delete();
		}
		log.info(file.toString());
		FileUtils.writeStringToFile(file, makeText, "UTF-8");
		if (!file.isFile()) {
			return false;
		}
		return FileUtils.sizeOf(file) > 0;
	}

	/**
	 * 绑定域名,增加server
	 * 
	 * @return
	 * @throws IOException
	 */
	public synchronized boolean bandleDomain(Agent agent, NginxServerConf nginxServerConf) throws IOException {
		if (!nginxOperate.boolTest()) {
			log.error("nginx -t 测试失败，错误内容：" + nginxOperate.test());
			return false;
		}

		String makeIncludeFile = makeIncludeFile(agent.getId(), nginxServerConf.getServerName());

		if (!make(agent.getId(), nginxServerConf)) {
			log.error("agent生成对应域名的server失败! agent: " + agent.toString() + " nginxServerConf: " + nginxServerConf.toString());
			return false;
		}

		if (!nginxOperate.boolTest()) {
			log.error("agent生成对应域名的server后，nginx -t 测试失败! 错误内容: " + nginxOperate.test() + " agent: " + agent.toString() + " nginxServerConf: "
					+ nginxServerConf.toString());
			File file = new File(makeIncludeFile);
			if (file.isFile()) {
				file.delete();
			}
			return false;
		}

		if (!nginxOperate.boolReload()) {
			log.error("agent生成对应域名的server后，nginx -s reload 热重启失败! 错误内容: " + nginxOperate.reload() + " agent: " + agent.toString() + " nginxServerConf: "
					+ nginxServerConf.toString());
			File file = new File(makeIncludeFile);
			if (file.isFile()) {
				file.delete();
			}
			return false;
		}

		if (!nginxOperate.boolTest()) {
			log.error("nginx -t 测试失败，错误内容：" + nginxOperate.test());
			return false;
		}

		return true;
	}

}
